// 攻击链服务 - 处理新的三列CSV格式
export interface AttackChainRow {
  parent_drs_in_ip: string      // 前一层前端节点IP
  parent_drs_backend_ip: string // 前一层后端节点IP  
  child_drs_in_ips: string      // 后一层前端节点IPs (逗号分隔)
}

export interface AttackChainCsvData {
  rows: AttackChainRow[]
  timestamp: string
  attackId: string
}

class AttackChainService {
  /**
   * 将拓扑结构转换为三列CSV格式的攻击链数据
   * @param nodes 节点数组
   * @param connections 连接数组
   * @param attackTarget 攻击目标
   * @returns AttackChainCsvData
   */
  convertTopologyToAttackChain(
    nodes: Array<{
      id: number
      name: string
      backends: number
      frontendIp?: string
      backendIps?: string[]
      level?: number
    }>,
    connections: Array<{
      from: { nodeId: number | 'target'; kind: 'frontend' | 'backend' | 'target'; backendIndex?: number }
      to: { nodeId: number | 'target'; kind: 'frontend' | 'backend' | 'target'; backendIndex?: number }
    }>,
    attackTarget?: { ip: string; port: number }
  ): AttackChainCsvData {
    const attackRows: AttackChainRow[] = []
    
    // 创建节点ID到节点的映射
    const nodeMap = new Map<number, typeof nodes[0]>()
    nodes.forEach(node => {
      nodeMap.set(node.id, node)
    })
    
    // 筛选出从backend到frontend的连接
    const backendToFrontendConnections = connections.filter(conn => 
      conn.from.kind === 'backend' && conn.to.kind === 'frontend'
    )
    
    // 按parent节点和backend索引分组连接
    // key: "parentNodeId_backendIndex"
    const connectionGroups = new Map<string, Set<number>>() // value: child node IDs (使用Set避免重复)
    
    backendToFrontendConnections.forEach(conn => {
      if (conn.from.nodeId === 'target' || conn.to.nodeId === 'target') return
      
      const parentNodeId = conn.from.nodeId
      const backendIndex = conn.from.backendIndex ?? 0
      const childNodeId = conn.to.nodeId
      
      const key = `${parentNodeId}_${backendIndex}`
      
      if (!connectionGroups.has(key)) {
        connectionGroups.set(key, new Set<number>())
      }
      connectionGroups.get(key)!.add(childNodeId as number)
    })
    
    // 为每个连接组创建攻击链行
    connectionGroups.forEach((childNodeIdsSet, key) => {
      const [parentNodeIdStr, backendIndexStr] = key.split('_')
      const parentNodeId = parseInt(parentNodeIdStr)
      const backendIndex = parseInt(backendIndexStr)
      
      const parentNode = nodeMap.get(parentNodeId)
      if (!parentNode || !parentNode.frontendIp || !parentNode.backendIps) return
      
      const backendIp = parentNode.backendIps[backendIndex]
      if (!backendIp) return
      
      // 收集所有子节点的前端IP（使用Set去重，避免重复连接导致的重复IP）
      const childFrontendIpsSet = new Set<string>()
      childNodeIdsSet.forEach(childNodeId => {
        const childNode = nodeMap.get(childNodeId)
        if (childNode && childNode.frontendIp) {
          childFrontendIpsSet.add(childNode.frontendIp)
        }
      })
      
      const childFrontendIps = Array.from(childFrontendIpsSet)
      if (childFrontendIps.length > 0) {
        attackRows.push({
          parent_drs_in_ip: parentNode.frontendIp,
          parent_drs_backend_ip: backendIp,
          child_drs_in_ips: childFrontendIps.join(',')
        })
      }
    })
    
    // 处理特殊情况：如果只有根节点直接连接到攻击目标，需要生成一行数据
    // 识别根节点（没有其他节点连接到其前端的节点）
    const connectedFrontendNodeIds = new Set<number>()
    connections.forEach(conn => {
      if (conn.to.kind === 'frontend' && conn.to.nodeId !== 'target' && typeof conn.to.nodeId === 'number') {
        connectedFrontendNodeIds.add(conn.to.nodeId)
      }
    })
    
    // 找到所有根节点（前端没有被连接的节点）
    const rootNodes = nodes.filter(node => !connectedFrontendNodeIds.has(node.id))
    
    // 如果存在根节点，检查是否有根节点直接连接到攻击目标
    if (rootNodes.length > 0 && attackTarget && attackRows.length === 0) {
      // 查找从根节点后端到攻击目标的连接
      const backendToTargetConnections = connections.filter(conn => 
        conn.from.kind === 'backend' && 
        conn.to.kind === 'target' && 
        typeof conn.from.nodeId === 'number'
      )
      
      // 按根节点和backend索引分组
      const rootToTargetGroups = new Map<string, number>() // key: "nodeId_backendIndex", value: count
      
      backendToTargetConnections.forEach(conn => {
        const nodeId = conn.from.nodeId as number
        const backendIndex = conn.from.backendIndex ?? 0
        
        // 检查是否是根节点
        if (rootNodes.some(root => root.id === nodeId)) {
          const key = `${nodeId}_${backendIndex}`
          rootToTargetGroups.set(key, (rootToTargetGroups.get(key) || 0) + 1)
        }
      })
      
      // 为每个根节点到攻击目标的连接生成一行数据
      rootToTargetGroups.forEach((count, key) => {
        const [nodeIdStr, backendIndexStr] = key.split('_')
        const nodeId = parseInt(nodeIdStr)
        const backendIndex = parseInt(backendIndexStr)
        
        const rootNode = rootNodes.find(n => n.id === nodeId)
        if (rootNode && rootNode.frontendIp && rootNode.backendIps) {
          const backendIp = rootNode.backendIps[backendIndex]
          if (backendIp) {
            // 使用攻击目标IP作为子节点IP
            attackRows.push({
              parent_drs_in_ip: rootNode.frontendIp,
              parent_drs_backend_ip: backendIp,
              child_drs_in_ips: attackTarget.ip
            })
          }
        }
      })
    }
    
    return {
      rows: attackRows,
      timestamp: new Date().toISOString(),
      attackId: this.generateAttackId()
    }
  }

  /**
   * 生成三列CSV格式的字符串
   * @param attackData 攻击链数据
   * @returns CSV字符串
   */
  generateCsvString(attackData: AttackChainCsvData): string {
    const csvRows: string[] = []
    
    // CSV头部
    csvRows.push('parent_drs_in_ip,parent_drs_backend_ip,child_drs_in_ips')
    
    // 数据行
    attackData.rows.forEach(row => {
      csvRows.push(`${row.parent_drs_in_ip},${row.parent_drs_backend_ip},"${row.child_drs_in_ips}"`)
    })
    
    return csvRows.join('\n')
  }

  /**
   * 下载CSV文件
   * @param csvContent CSV内容
   * @param filename 文件名
   */
  downloadCsvFile(csvContent: string, filename?: string): void {
    try {
      const defaultFilename = `attack_chain_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.csv`
      const finalFilename = filename || defaultFilename
      
      // 创建Blob对象
      const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
      
      // 创建下载链接
      const link = document.createElement('a')
      if (link.download !== undefined) {
        const url = URL.createObjectURL(blob)
        link.setAttribute('href', url)
        link.setAttribute('download', finalFilename)
        link.style.visibility = 'hidden'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        URL.revokeObjectURL(url)
      }
      
      console.log('CSV文件已下载:', finalFilename)
    } catch (error) {
      console.error('下载CSV文件失败:', error)
      throw new Error(`下载失败: ${error instanceof Error ? error.message : '未知错误'}`)
    }
  }

  /**
   * 生成攻击ID
   * @returns string
   */
  private generateAttackId(): string {
    return `attack_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  /**
   * 验证攻击链数据
   * @param attackData 攻击链数据
   * @returns 验证结果
   */
  validateAttackData(attackData: AttackChainCsvData): { valid: boolean; errors: string[] } {
    const errors: string[] = []
    
    if (!attackData.rows || attackData.rows.length === 0) {
      errors.push('攻击链数据为空')
      return { valid: false, errors }
    }
    
    attackData.rows.forEach((row, index) => {
      if (!row.parent_drs_in_ip || !row.parent_drs_backend_ip || !row.child_drs_in_ips) {
        errors.push(`第${index + 1}行数据不完整`)
      }
      
      // 验证IP格式（简单验证）
      const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/
      if (!ipRegex.test(row.parent_drs_in_ip)) {
        errors.push(`第${index + 1}行父节点前端IP格式错误: ${row.parent_drs_in_ip}`)
      }
      if (!ipRegex.test(row.parent_drs_backend_ip)) {
        errors.push(`第${index + 1}行父节点后端IP格式错误: ${row.parent_drs_backend_ip}`)
      }
      
      // 验证子节点IPs
      const childIps = row.child_drs_in_ips.split(',')
      childIps.forEach(childIp => {
        const trimmedIp = childIp.trim()
        if (!ipRegex.test(trimmedIp)) {
          errors.push(`第${index + 1}行子节点IP格式错误: ${trimmedIp}`)
        }
      })
    })
    
    return {
      valid: errors.length === 0,
      errors
    }
  }
}

// 导出单例实例
export const attackChainService = new AttackChainService()












